package com.cosyhut.blocks.display;

import com.jme.scene.Node;
import com.jme.scene.shape.*;
import com.jme.math.*;
import com.jme.renderer.*;
import com.jme.scene.state.*;

import com.cosyhut.blocks.jode.*;
import com.cosyhut.blocks.factory.*;

public class DVisual {

	static final int _rate = 15;

	static final float _centerRadius = BFactory.units(5);

	static final float _axisRadius = BFactory.units(2);

	static final float _axisLength = BFactory.units(100);

	public static Node createXYZ(Renderer renderer) {
		Node result = new Node();

		Sphere center = new Sphere(null, _rate, _rate, _centerRadius);
		MaterialState m = renderer.createMaterialState();
		m.setAmbient(new ColorRGBA(1f, 1f, 0f, 1));
		center.setRenderState(m);
		result.attachChild(center);

		Node x = createVector(renderer, new Vector3f(0, 0, 0), new Vector3f(
				_axisLength, 0, 0), new ColorRGBA(1, 0, 0, 1));
		result.attachChild(x);
		Node y = createVector(renderer, new Vector3f(0, 0, 0), new Vector3f(0,
				_axisLength, 0), new ColorRGBA(0, 1, 0, 1));
		result.attachChild(y);
		Node z = createVector(renderer, new Vector3f(0, 0, 0), new Vector3f(0,
				0, _axisLength), new ColorRGBA(0, 0, 1, 1));
		result.attachChild(z);

		return result;
	}

	public static Node createDot(Renderer renderer) {
		Node result = new Node();

		Sphere center = new Sphere(null, _rate, _rate, _centerRadius);
		MaterialState m = renderer.createMaterialState();
		m.setAmbient(new ColorRGBA(1f, 1f, 0f, 1));
		center.setRenderState(m);
		result.attachChild(center);

		return result;
	}

	public static Node createVector(Renderer renderer, Vector3f begining,
			Vector3f ending, ColorRGBA color) {
		Node result = new Node();
		//float length = ending.distance(begining);
		
		MaterialState m = renderer.createMaterialState();
		m.setAmbient(color);

		Cylinder axis = new Cylinder(null, _rate, _rate, _axisRadius, _axisLength);
		Quaternion axis_r = new Quaternion();
		axis_r.lookAt(ending.add(begining.negate()), new Vector3f(1, 1, 1));
		axis.setLocalRotation(axis_r);
		Vector3f axis_t = (Vector3f)begining.clone();
		axis_t.z += _axisLength/2;
		axis_t = axis_r.mult(axis_t);
		axis.setLocalTranslation(axis_t);

		axis.setRenderState(m);
		result.attachChild(axis);

		Sphere arrow = new Sphere(null, _rate, _rate, _centerRadius);
		Quaternion arrow_r = new Quaternion();
		arrow_r.lookAt(ending.add(begining.negate()), new Vector3f(1, 1, 1));
		Vector3f arrow_t = (Vector3f)begining.clone();
		arrow_t.z += _axisLength;
		arrow_t = arrow_r.mult(arrow_t);
		arrow.setLocalTranslation(arrow_t);
		//arrow_r.inverseLocal();
		//arrow.setLocalRotation(arrow_r);
		
		arrow.setRenderState(m);
		result.attachChild(arrow);

		return result;
	}

	public static Node createNode(ODEGeom geom) {
		Node result;
		int type = geom.getModel().getType();

		if (jodeConstants.dBoxClass == type) {
			MGeomBox m = (MGeomBox) geom.getModel();
			result = createBox(m.getX(), m.getY(), m.getZ());
		} else if (jodeConstants.dSphereClass == type) {
			MGeomSphere m = (MGeomSphere) geom.getModel();
			result = createSphere(m.getRadius());
		} else if (jodeConstants.dCylinderClass == type) {
			MGeomCylinder m = (MGeomCylinder) geom.getModel();
			result = createCylinder(m.getRadius(), m.getLength());
		} else {
			result = null;
			assert (false); // other geom type no supportted now
		}

		result.setLocalTranslation(geom.getPosition());
		result.setLocalRotation(geom.getRotation());
		return result;
	}

	public static Node createBox(float x, float y, float z) {
		Node result = new Node();
		result.attachChild(new Box(null, new com.jme.math.Vector3f(), x / 2,
				y / 2, z / 2));
		return result;
	}

	public static Node createSphere(float radius) {
		Node result = new Node();
		result.attachChild(new Sphere(null, _rate, _rate, radius));
		return result;
	}

	public static Node createCylinder(float radius, float length) {
		Node result = new Node();
		result.attachChild(new Cylinder(null, _rate, _rate, radius, length));
		return result;
	}

	public static Node createCapsule(float radius, float length) {
		Node result = new Node();
		result.attachChild(new Cylinder(null, _rate, _rate, radius, length));
		Dome dome1 = new Dome(null, _rate, _rate, radius);
		Matrix3f rotation = new Matrix3f();
		rotation.loadIdentity();
		rotation.fromAngleAxis((float) (Math.PI / 2f),
				new com.jme.math.Vector3f(1f, 0f, 0f));
		dome1.setLocalRotation(rotation);
		dome1
				.setLocalTranslation(new com.jme.math.Vector3f(0f, 0f,
						length / 2));
		result.attachChild(dome1);

		Dome dome2 = new Dome(null, _rate, _rate, radius);
		rotation.loadIdentity();
		rotation.fromAngleAxis((float) (Math.PI / 2f * 3),
				new com.jme.math.Vector3f(1f, 0f, 0f));
		dome2.setLocalRotation(rotation);
		dome2.setLocalTranslation(new com.jme.math.Vector3f(0f, 0f,
				0 - length / 2));
		result.attachChild(dome2);

		return result;
	}
}
